#!/bin/bash
# Copyright (C) 2019 Checkmk GmbH - License: GNU General Public License v2
# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
# conditions defined in the file COPYING, which is part of this source code package.

# Reason for this no-op: shellcheck disable=... before the first command disables the error for the
# entire script.
:

# Disable unused variable error (needed to keep track of version)
# shellcheck disable=SC2034
CMK_VERSION="2.5.0b1"

# sample output of pgrep command
# 1051 /usr/bin/redis-server 127.0.0.1:6380
# 1324 /usr/bin/redis-server 127.0.0.1:6379

# example cfg file /etc/check_mk/mk_redis.cfg
#
# REDIS_INSTANCES=(My_First_Redis My_Second_Redis My_socket_Redis)
#
# REDIS_HOST_My_First_Redis="127.0.0.1"
# REDIS_PORT_My_First_Redis="6380"
# REDIS_PASSWORD_My_First_Redis='MYPASSWORD'
#
# REDIS_HOST_My_Second_Redis="127.0.0.1"
# REDIS_PORT_My_Second_Redis="6379"

# REDIS_HOST_My_socket_Redis="/var/redis/redis.sock"
# REDIS_PORT_My_socket_Redis="unix-socket"

load_config() {
    # source optional configuration file
    if [ -e "$MK_CONFDIR/mk_redis.cfg" ]; then
        # shellcheck source=../cfg_examples/mk_redis.cfg
        . "$MK_CONFDIR/mk_redis.cfg"
    fi
}

redis_args() {
    INSTANCE=$1

    HOST="REDIS_HOST_$INSTANCE"
    PORT="REDIS_PORT_$INSTANCE"
    PASSWORD="REDIS_PASSWORD_$INSTANCE"

    # if autodetection is used, rewrite instance name for section output
    if [[ "$IS_DETECTED" == true ]]; then
        INSTANCE="${!HOST};${!PORT}"
    fi

    if [[ "${!PORT}" == "unix-socket" ]]; then
        REDIS_ARGS=("-s" "${!HOST}")
    else
        REDIS_ARGS=("-h" "${!HOST}" "-p" "${!PORT}")
    fi

    if [[ "${!PASSWORD}" ]] && [[ "${!PASSWORD}" != "None" ]]; then
        REDIS_CLI_COMMAND="REDISCLI_AUTH='${!PASSWORD}' redis-cli"
    else
        REDIS_CLI_COMMAND="redis-cli"
    fi

    REDIS_ARGS+=("info")
}

main() {
    set -e -o pipefail

    REDIS_INSTANCES=()
    IS_DETECTED=false

    load_config

    # if no servers in config file, try to detect
    if [ ${#REDIS_INSTANCES[@]} -eq 0 ]; then
        IS_DETECTED=true
        # find instances and remove entries like "*:6879", possible with docker container
        DETECTED=$(pgrep -xa "redis-server" 2>/dev/null | awk '/:[0-9]+/ && !/\*/ || /unixsocket:.*/ { print $3 }')

        # add found redis instances
        for REDIS_INSTANCE in $DETECTED; do
            for inst in $REDIS_INSTANCE; do
                IFS=":" read -ra parts <<<"$inst"

                # dot of IP can not be used in variable names
                REDIS_NAME=$(echo "$inst" | tr ':./' '_')

                # create dynamic variables
                if [[ "${parts[0]}" == "unixsocket" ]]; then
                    # handle checkmk redis instances as configured sockets
                    declare "REDIS_HOST_$REDIS_NAME=${parts[1]}"
                    declare "REDIS_PORT_$REDIS_NAME=unix-socket"
                else
                    declare "REDIS_HOST_$REDIS_NAME=${parts[0]}"
                    declare "REDIS_PORT_$REDIS_NAME=${parts[1]}"
                fi

                # append instance to array
                REDIS_INSTANCES+=("${REDIS_NAME}")
            done
        done
    fi

    # print redis section, if servers are found
    [ "${REDIS_INSTANCES[*]}" ] || exit 0

    echo "<<<redis_info:sep(58)>>>"

    for INSTANCE in "${REDIS_INSTANCES[@]}"; do
        redis_args "${INSTANCE}"
        # print server section
        echo "[[[$INSTANCE|${!HOST}|${!PORT}]]]"

        if [[ "${!HOST}" == /omd/sites/* ]]; then
            # use site redis-cli for redis instances in site
            IFS="/" read -ra ADDR <<<"${!HOST}"
            output=$(waitmax 3 bash -c "/omd/sites/${ADDR[3]}/bin/redis-cli ${REDIS_ARGS[*]}" 2>&1 || true)
        else
            output=$(waitmax 3 bash -c "${REDIS_CLI_COMMAND} ${REDIS_ARGS[*]}" 2>&1 || true)
        fi

        if [[ "$output" == *"Could not connect to Redis at ${!HOST}: Permission denied"* ]]; then
            # mark error explicitly for easier parsing
            echo "error: $output"
        else
            echo "$output"
        fi

    done

}

[ -z "${MK_SOURCE_ONLY}" ] && main "$@"
